package com.crt.nexus.oauth.endpoint;

import com.crt.nexus.core.response.R;
import com.crt.nexus.oauth.authorization.AuthenticationBuilder;
import com.crt.nexus.oauth.service.UserAuthenticationManager;
import com.crt.nexus.security.authentication.AuthenticationToken;
import com.crt.nexus.security.domain.bean.TokenBean;
import com.crt.nexus.security.util.WebUtils;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.security.KeyPair;
import java.security.interfaces.RSAPublicKey;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserEndpoint {

    private final AuthenticationBuilder builder;
    private final UserAuthenticationManager manager;
    private final KeyPair keyPair;

    @RequestMapping(value = "token", method = {GET, POST}, params = {"grant_type=password"}, produces = APPLICATION_JSON_VALUE)
    public R<TokenBean> password(HttpServletRequest request) {
        String username = request.getParameter("username");
        if (Strings.isNullOrEmpty(username)) throw new BadCredentialsException("用户名不能为空");
        String password = request.getParameter("password");
        if (Strings.isNullOrEmpty(password)) throw new BadCredentialsException("密码不能为空");
        AuthenticationToken authentication = new AuthenticationToken(username, password, WebUtils.getClient(request));
        TokenBean token = builder.buildPassword(manager.authenticate(authentication));
        return R.ok(token);
    }

    @RequestMapping(value = "token", method = GET, params = {"grant_type=refresh_token"}, produces = APPLICATION_JSON_VALUE)
    public R<TokenBean> refresh(HttpServletRequest request) {
        String refreshToken = request.getParameter("refresh_token");
        if (Strings.isNullOrEmpty(refreshToken)) throw new BadCredentialsException("刷新令牌不能为空");
        RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
        Jwt jwt = NimbusJwtDecoder.withPublicKey(publicKey).build().decode(refreshToken);
        Authentication authentication = new AuthenticationToken(jwt, null, WebUtils.getClient(request));
        TokenBean token = builder.buildRefresh(manager.authenticate(authentication));
        return R.ok(token);
    }

}
